package com.gzsxy.esjy.service.netty.client;


import com.gzsxy.esjy.request.impl.FileHttpServletRequest;
import com.gzsxy.esjy.response.NettyHttpResponse;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

/**
 * 异步httpClient（暂无用）
 * @author zhangxiaolong
 * @date 2022/7/11 9:36
 */
public class NettyHttpClient {
	
	/**
	 * netty客户端(只有一个)
	 */
	private static Bootstrap bootstrap = initClient();

	/**
	 * 初始化Bootstrap(只能有一个)
	 * @return
	 */
	private static Bootstrap initClient(){
		 NioEventLoopGroup workerGroup = new NioEventLoopGroup();
		 Bootstrap bs = new Bootstrap();
         bs.group(workerGroup)
         .channel(NioSocketChannel.class)
         .option(ChannelOption.SO_KEEPALIVE, true)
         .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5)
         .handler(new LoggingHandler(LogLevel.INFO))
         .handler(new ChildChannelHandler());
        return bs ;
	}

	/**
	 * 内部类
	 * @author hezhiyuan
	 *
	 */
	private static class ChildChannelHandler extends ChannelInitializer<Channel> {

		@Override
        protected void initChannel(Channel channel) throws Exception {
			ChannelManager.addListener(channel);
            channel.pipeline()
             	.addLast("coder", new HttpClientCodec())
             	.addLast(new IdleStateHandler(5, 7, 120,TimeUnit.SECONDS))
             	.addLast("http-chunked", new ChunkedWriteHandler()) ;
        }
    }

	/**
	 * get代理
	 * @param ip
	 * @param port
	 * @param out
	 * @param request
	 */
	public static void proxyGET(String ip, Integer port, Channel out, FileHttpServletRequest request) {
		String tag = ip+":"+port;
		Channel operateChannel = ChannelManager.operateChannel(tag, null, true);
		if(operateChannel != null) {
			request(request, operateChannel,tag,out);
			return ;
		}
		bootstrap.connect(ip,port).addListener(new ChannelFutureListener() {
			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				Channel channel = future.channel();
				if (future.isSuccess()) {
					request(request, channel,tag,out);
	            } else {
	            	FullHttpResponse create = NettyHttpResponse.create(HttpResponseStatus.BAD_GATEWAY, "网关超时: "+tag, request.getCharset().displayName()) ;
	            	out.writeAndFlush(create) ;
	            	channel.close();
	            }
			}
	    }) ;
	}
	
	/**
	 * 
	 * @param request
	 * @param channel
	 * @param tag
	 * @param out
	 */
	private static void request(FileHttpServletRequest request, Channel channel, String tag, Channel out) {
		TransChannelHandler transChannelHandler = channel.pipeline().get(TransChannelHandler.class);
		if(transChannelHandler == null) {
			channel.pipeline().addLast(new TransChannelHandler(tag,out));
		}else {
			transChannelHandler.setChannel(out);
		}
		DefaultFullHttpRequest defaultFullHttpRequest = new DefaultFullHttpRequest(request.getProtocolVersion(), HttpMethod.GET, request.getUri()) ;
		defaultFullHttpRequest.headers().add(request.getHeaders());
		channel.writeAndFlush(defaultFullHttpRequest);
	}
	
}
